package models;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.mchange.v2.lang.Coerce;

import java.util.*;

public class Operacoes {

	public Connection conexao;

	public Operacoes() {
		conexao = new FabricaConexao().getConnection();
	}

	public void inserirNovoMaterial(Materiais novoMaterial,
			PropriedadesTermicas novasPropriedades, Resultados novosResultados,
			CategoriaNBR novaCategoria, MaterialBase novoMaterialBase,
			Tipo novoTipo, Aplicacao novaAplicacao1, Aplicacao novaAplicacao2,
			Aplicacao novaAplicacao3) throws SQLException {

		inserirTabelaMateriais(novoMaterial);
		// recopera o id do ultimo registro adicionado, no caso esse que foi
		// adicionado agora.
		// vai servir para adicionar as relacoes.
		int idMateriais = pegarUltimoIdMateriais();
		/* System.out.println(idMateriais); */

		inserirTabelaPropriedadesTermicas(novasPropriedades);
		int idPropriedadesTermicas = pegarUltimoIdPropriedadesTermicas();
		/* System.out.println(idPropriedadesTermicas); */

		// novo elemento da relação Materiais e Propriedades Termicas
		inserirTabelaMateriaisRelPropriedadesTermicas(idMateriais,
				idPropriedadesTermicas);

		inserirTabelaResultados(novosResultados);
		int idResultados = pegarUltimoIdResultados();
		/* System.out.println(idResultados); */

		// novo elemento da relação Materiais e Resultados
		inserirTabelaMateriaisRelResultados(idMateriais, idResultados);

		// testa se a categoriaNBR foi preenchida
		if (novaCategoria != null) {
			// recopera o id correspondente a categoria dado
			int idCategoriaNBR = pegarIdCategoriaNBRPeloNome(novaCategoria);

			// faz a relação de Materiais com a Categoria
			inserirTabelaMateriaisRelCategoriaNBR(idMateriais, idCategoriaNBR);

		}

		if (novoMaterialBase != null) {
			int idNovoMaterialBase = pegarIdMaterialBasePeloNome(novoMaterialBase);

			inserirTabelaMateriaisRelMaterialBase(idMateriais,
					idNovoMaterialBase);
		}

		if (novoTipo != null) {
			int idNovoTipo = pegarIdTipoPeloNome(novoTipo);

			inserirTabelaMateriaisRelTipo(idMateriais, idNovoTipo);
		}

		int idNovaAplicacao1 = pegarIdAplicacaoPeloNome(novaAplicacao1);

		int idNovaAplicacao2 = pegarIdAplicacaoPeloNome(novaAplicacao2);

		int idNovaAplicacao3 = pegarIdAplicacaoPeloNome(novaAplicacao3);

		inserirTabelaAplicacoes(idNovaAplicacao1, idNovaAplicacao2,
				idNovaAplicacao3);

		int idAplicacoes = pegarUltimoIdAplicacoes();

		inserirTabelaMateriaisRelAplicacoes(idMateriais, idAplicacoes);

	}

	// adiciona a Tabela NovoMaterial;
	public void inserirTabelaMateriais(Materiais novoMaterial)
			throws SQLException {

		String sql = "insert into Materiais (ptCompleta,nomenclaturaTemplate, espessura, descricao,funcaoRevit,"
				+ "novaNomenclatura, linkCalculo, linkModelagem, custoPorUnidade, conteudoDeEnergia, fornecedor,"
				+ "contato, link, fonte, certificadoOITI) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";

		PreparedStatement stm = conexao.prepareStatement(sql);

		stm.setString(1, novoMaterial.ptCompleta);
		stm.setString(2, novoMaterial.nomenclaturaTemplate);
		stm.setString(3, novoMaterial.espessura);
		stm.setString(4, novoMaterial.descricao);
		stm.setString(5, novoMaterial.funcaoRevit);
		stm.setString(6, novoMaterial.novaNomenclatura);
		stm.setString(7, novoMaterial.linkCalculo);
		stm.setString(8, novoMaterial.linkModelagem);
		stm.setString(9, novoMaterial.custoPorUnidade);
		stm.setString(10, novoMaterial.conteudoDeEnergia);
		stm.setString(11, novoMaterial.fornecedor);
		stm.setString(12, novoMaterial.contato);
		stm.setString(13, novoMaterial.link);
		stm.setString(14, novoMaterial.fonte);
		stm.setString(15, novoMaterial.certificadoOITI);

		stm.execute();
		stm.close();
	}

	public int pegarUltimoIdMateriais() throws SQLException {

		Integer resultado = null;
		String sql = "select max(id) from Materiais";
		PreparedStatement stm = conexao.prepareStatement(sql);
		ResultSet rs = stm.executeQuery();

		if (rs.next()) {
			resultado = rs.getInt("max(id)");
		}
		stm.close();
		return resultado;
	}

	public void inserirTabelaPropriedadesTermicas(
			PropriedadesTermicas novasPropriedades) throws SQLException {
		String sql = "insert into PropriedadesTermicas (massaAparente, condutividadeTermica, calorEspecifico)"
				+ " values(?,?,?)";

		PreparedStatement stm = conexao.prepareStatement(sql);
		stm.setString(1, novasPropriedades.massaAparente);
		stm.setString(2, novasPropriedades.condutividadeTermica);
		stm.setString(3, novasPropriedades.calorEspecifico);

		stm.execute();
		stm.close();

	}

	public int pegarUltimoIdPropriedadesTermicas() throws SQLException {

		Integer resultado = null;
		String sql = "select max(id) from PropriedadesTermicas";
		PreparedStatement stm = conexao.prepareStatement(sql);
		ResultSet rs = stm.executeQuery();

		if (rs.next()) {
			resultado = rs.getInt("max(id)");
		}

		stm.close();
		return resultado;
	}

	public void inserirTabelaResultados(Resultados novosResultados)
			throws SQLException {

		String sql = "insert into Resultados (resistencia, capacidadeTermica, atrasoTermico) values (?,?,?)";
		PreparedStatement stm = conexao.prepareStatement(sql);
		stm.setString(1, novosResultados.resistencia);
		stm.setString(2, novosResultados.capacidadeTermica);
		stm.setString(3, novosResultados.atrasoTermico);

		stm.execute();
		stm.close();
	}

	public int pegarUltimoIdResultados() throws SQLException {

		Integer resultado = null;
		String sql = "select max(id) from Resultados";
		PreparedStatement stm = conexao.prepareStatement(sql);
		ResultSet rs = stm.executeQuery();

		if (rs.next()) {
			resultado = rs.getInt("max(id)");
		}

		stm.close();
		return resultado;

	}

	public int pegarIdCategoriaNBRPeloNome(CategoriaNBR novaCategoria)
			throws SQLException {

		Integer resultado = null;
		String sql = "select id from CategoriaNBR where nomeCategoria = (?)";
		PreparedStatement stm = conexao.prepareStatement(sql);
		stm.setString(1, novaCategoria.nomeCategoria.toUpperCase());
		ResultSet rs = stm.executeQuery();

		if (rs.next()) {
			resultado = rs.getInt("id");
		}

		stm.close();
		// Quaisquer erros, cai no id 1
		return (resultado == null) ? 1 : resultado;
	}

	public int pegarIdMaterialBasePeloNome(MaterialBase novoMaterialBase)
			throws SQLException {
		Integer resultado = null;
		String sql = "select id from MaterialBase where nomeMaterial = (?)";
		PreparedStatement stm = conexao.prepareStatement(sql);
		stm.setString(1, novoMaterialBase.nomeMaterial.toUpperCase());
		ResultSet rs = stm.executeQuery();

		if (rs.next()) {
			resultado = rs.getInt("id");
		}

		stm.close();
		// Quaisquer erros, cai no id 1
		return (resultado == null) ? 1 : resultado;
	}

	public int pegarIdTipoPeloNome(Tipo novoTipo) throws SQLException {
		Integer resultado = null;
		String sql = "select id from Tipo where nomeTipo = (?)";
		PreparedStatement stm = conexao.prepareStatement(sql);
		stm.setString(1, novoTipo.nomeTipo.toUpperCase());
		ResultSet rs = stm.executeQuery();

		if (rs.next()) {
			resultado = rs.getInt("id");
		}

		stm.close();

		// Quaisquer erros, cai no id 1
		return (resultado == null) ? 1 : resultado;
	}

	public int pegarIdAplicacaoPeloNome(Aplicacao novaAplicacao)
			throws SQLException {
		Integer resultado = null;
		if (novaAplicacao.nomeAplicacao != null) {
			String sql = "select id from Aplicacao where nomeAplicacao = (?)";
			PreparedStatement stm = conexao.prepareStatement(sql);
			stm.setString(1, novaAplicacao.nomeAplicacao.toUpperCase());
			ResultSet rs = stm.executeQuery();

			if (rs.next()) {
				resultado = rs.getInt("id");
			}
			stm.close();
		}
		// Quaisquer erros, cai no id 1
		return (resultado == null) ? 1 : resultado;
	}

	public void inserirTabelaMateriaisRelPropriedadesTermicas(int idMateriais,
			int idPropriedadesTermicas) throws SQLException {

		String sql = "insert into MateriaisRelPropriedadesTermicas (idMateriais, idPropriedadesTermicas) values(?,?)";
		PreparedStatement stm = conexao.prepareStatement(sql);
		stm.setInt(1, idMateriais);
		stm.setInt(2, idPropriedadesTermicas);

		stm.execute();
		stm.close();
	}

	public void inserirTabelaMateriaisRelResultados(int idMateriais,
			int idResultados) throws SQLException {

		String sql = "insert into MateriaisRelResultados (idMateriais, idResultados) values (?,?)";
		PreparedStatement stm = conexao.prepareStatement(sql);
		stm.setInt(1, idMateriais);
		stm.setInt(2, idResultados);
		stm.execute();
		stm.close();
	}

	public void inserirTabelaMateriaisRelCategoriaNBR(int idMateriais,
			int idCategoriaNBR) throws SQLException {

		String sql = "insert into MateriaisRelCategoriaNBR (idMateriais, idCategoriaNBR) values (?,?)";
		PreparedStatement stm = conexao.prepareStatement(sql);
		stm.setInt(1, idMateriais);
		stm.setInt(2, idCategoriaNBR);
		stm.execute();
		stm.close();
	}

	public void inserirTabelaMateriaisRelMaterialBase(int idMateriais,
			int idMaterialBase) throws SQLException {

		String sql = "insert into MateriaisRelMaterialBase (idMateriais, idMaterialBase) values (?,?)";
		PreparedStatement stm = conexao.prepareStatement(sql);
		stm.setInt(1, idMateriais);
		stm.setInt(2, idMaterialBase);
		stm.execute();
		stm.close();
	}

	public void inserirTabelaMateriaisRelTipo(int idMateriais, int idTipo)
			throws SQLException {

		String sql = "insert into MateriaisRelTipo (idMateriais, idTipo) values (?,?)";
		PreparedStatement stm = conexao.prepareStatement(sql);
		stm.setInt(1, idMateriais);
		stm.setInt(2, idTipo);
		stm.execute();
		stm.close();
	}

	public void inserirTabelaAplicacoes(int idAplicacao1, int idAplicacao2,
			int idAplicacao3) throws SQLException {

		String sql = "insert into Aplicacoes (idAplicacao1, idAplicacao2, idAplicacao3) values (?,?,?)";
		PreparedStatement stm = conexao.prepareStatement(sql);
		stm.setInt(1, idAplicacao1);
		stm.setInt(2, idAplicacao2);
		stm.setInt(3, idAplicacao3);
		stm.execute();
		stm.close();
	}

	public int pegarUltimoIdAplicacoes() throws SQLException {

		Integer resultado = null;
		String sql = "select max(id) from Aplicacoes";
		PreparedStatement stm = conexao.prepareStatement(sql);
		ResultSet rs = stm.executeQuery();

		if (rs.next()) {
			resultado = rs.getInt("max(id)");
		}

		stm.close();
		return resultado;
	}

	public void inserirTabelaMateriaisRelAplicacoes(int idMateriais,
			int idAplicacoes) throws SQLException {

		String sql = "insert into MateriaisRelAplicacoes (idMateriais, idAplicacoes) values (?,?)";
		PreparedStatement stm = conexao.prepareStatement(sql);
		stm.setInt(1, idMateriais);
		stm.setInt(2, idAplicacoes);
		stm.execute();
		stm.close();
	}

	public List<Object> consultar() throws SQLException {
		List<Object> list = new LinkedList<Object>();

		String sql = "select * from Materiais";
		PreparedStatement stm = conexao.prepareStatement(sql);
		ResultSet rs = stm.executeQuery();

		while (rs.next()) {
			class Grupo {
				int id;
				Materiais material;
				PropriedadesTermicas termicas;
				Resultados resultados;
				List<Aplicacao> ap;
				CategoriaNBR catNBR;
				MaterialBase base;
				Tipo tipo;
			}

			Grupo grupo = new Grupo();

			/* Informações principais */
			grupo.material = new Materiais();
			grupo.id = rs.getInt(1);

			grupo.material.ptCompleta = rs.getString(2);
			grupo.material.nomenclaturaTemplate = rs.getString(3);
			grupo.material.espessura = rs.getString(4);
			grupo.material.descricao = rs.getString(5);
			grupo.material.funcaoRevit = rs.getString(6);
			grupo.material.novaNomenclatura = rs.getString(7);
			grupo.material.linkCalculo = rs.getString(8);
			grupo.material.linkModelagem = rs.getString(9);
			grupo.material.custoPorUnidade = rs.getString(10);
			grupo.material.conteudoDeEnergia = rs.getString(11);
			grupo.material.fornecedor = rs.getString(12);
			grupo.material.contato = rs.getString(13);
			grupo.material.link = rs.getString(14);
			grupo.material.fonte = rs.getString(15);
			grupo.material.certificadoOITI = rs.getString(16);

			ResultSet rsTmp;
			int other_id = 0;
			String table;

			/* Relações com Propriedades Térmicas */
			table = "PropriedadesTermicas";
			other_id = getRelId(table, grupo.id);
			sql = "select * from " + table + " ";
			sql += "where id = " + other_id;
			stm = conexao.prepareStatement(sql);
			rsTmp = stm.executeQuery();
			if (rsTmp.next()) {
				grupo.termicas = new PropriedadesTermicas();
				grupo.termicas.massaAparente = rsTmp.getString(2);
				grupo.termicas.condutividadeTermica = rsTmp.getString(3);
				grupo.termicas.calorEspecifico = rsTmp.getString(4);
			}

			/* Relações com Resultados */
			table = "Resultados";
			other_id = getRelId(table, grupo.id);
			sql = "select * from " + table + " ";
			sql += "where id = " + other_id;
			stm = conexao.prepareStatement(sql);
			rsTmp = stm.executeQuery();
			if (rsTmp.next()) {
				grupo.resultados = new Resultados();
				grupo.resultados.resistencia = rsTmp.getString(2);
				grupo.resultados.capacidadeTermica = rsTmp.getString(3);
				grupo.resultados.atrasoTermico = rsTmp.getString(4);
			}

			/* Relações com Categoria NBR */
			table = "CategoriaNBR";
			other_id = getRelId(table, grupo.id);
			sql = "select * from " + table + " ";
			sql += "where id = " + other_id;
			stm = conexao.prepareStatement(sql);
			rsTmp = stm.executeQuery();
			if (rsTmp.next()) {
				grupo.catNBR = new CategoriaNBR();
				grupo.catNBR.nomeCategoria = rsTmp.getString(2);
			}

			/* Relações com Material Base */
			table = "MaterialBase";
			other_id = getRelId(table, grupo.id);
			sql = "select * from " + table + " ";
			sql += "where id = " + other_id;
			stm = conexao.prepareStatement(sql);
			rsTmp = stm.executeQuery();
			if (rsTmp.next()) {
				grupo.base = new MaterialBase();
				grupo.base.nomeMaterial = rsTmp.getString(2);
			}

			/* Relações com Tipo */
			table = "Tipo";
			other_id = getRelId(table, grupo.id);
			sql = "select * from " + table + " ";
			sql += "where id = " + other_id;
			stm = conexao.prepareStatement(sql);
			rsTmp = stm.executeQuery();
			if (rsTmp.next()) {
				grupo.tipo = new Tipo();
				grupo.tipo.nomeTipo = rsTmp.getString(2);
			}

			/* Relações com Aplicações */
			table = "Aplicacoes";
			other_id = getRelId(table, grupo.id);
			sql = "select * from " + table + " ";
			sql += "where id = " + other_id;
			stm = conexao.prepareStatement(sql);
			rsTmp = stm.executeQuery();
			grupo.ap = new LinkedList<Aplicacao>();
			table = "Aplicacao";
			if (rsTmp.next())
				for (int i = 0; i < 3; i++) {
					other_id = rsTmp.getInt(i + 2);
					sql = "select * from " + table + " ";
					sql += "where id = " + other_id;
					stm = conexao.prepareStatement(sql);
					ResultSet rsTmp2 = stm.executeQuery();
					if (rsTmp2.next()) {
						grupo.ap.add(i, new Aplicacao());
						grupo.ap.get(i).nomeAplicacao = rsTmp2.getString(2);
					}
				}

			list.add(grupo);
		}
		stm.close();
		return list;
	}

	private int getRelId(String table, int id) throws SQLException {
		int other_id = 0;
		String sql;
		sql = "select id" + table + " ";
		sql += "from MateriaisRel" + table + " ";
		sql += "where idMateriais = " + id;
		PreparedStatement stm = conexao.prepareStatement(sql);
		ResultSet rs = stm.executeQuery();
		if (rs.next())
			other_id = rs.getInt(1);
		else
			other_id = -1;
		stm.close();
		return other_id;
	}

	public void remover(int id) throws SQLException {
		String sql;
		PreparedStatement stm;
		String[] tables1 = { "CategoriaNBR", "MaterialBase", "Tipo" };
		for (String i : tables1) {
			sql = "delete from MateriaisRel" + i + " where idMateriais = " + id;
			stm = conexao.prepareStatement(sql);
			stm.execute();
			stm.close();
		}
		String[] tables2 = { "Aplicacoes", "PropriedadesTermicas", "Resultados" };
		for (String i : tables2) {
			sql = "delete from " + i + " where id = " + getRelId(i, id);
			stm = conexao.prepareStatement(sql);
			stm.execute();
			sql = "delete from MateriaisRel" + i + " where idMateriais = " + id;
			stm = conexao.prepareStatement(sql);
			stm.execute();
			stm.close();
			stm.close();
		}
		sql = "delete from Materiais where id = " + id;
		stm = conexao.prepareStatement(sql);
		stm.execute();
		stm.close();
	}
}
